package org.example.Stream;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author : zhangbo
 * @data : 2024/7/22
 * @description :
 */
public class StreamTest {
    public static void main(String[] args) {

        Employee[] employees = new Employee[10];
        employees[0] = new Employee("Alice", 30, 50000.00, "HR", LocalDate.of(2018, 4, 23));
        employees[1] = new Employee("Bob", 25, 60000.00, "Engineering", LocalDate.of(2019, 6, 15));
        employees[2] = new Employee("Charlie", 40, 70000.00, "Marketing", LocalDate.of(2017, 3, 10));
        employees[3] = new Employee("David", 35, 55000.00, "技术部", LocalDate.of(2016, 8, 20));
        employees[4] = new Employee("Eva", 28, 48000.00, "HR", LocalDate.of(2020, 1, 5));
        employees[5] = new Employee("Frank", 45, 90000.00, "Management", LocalDate.of(2015, 5, 12));
        employees[6] = new Employee("Grace", 32, 62000.00, "Engineering", LocalDate.of(2018, 9, 21));
        employees[7] = new Employee("Heidi", 29, 51000.00, "技术部", LocalDate.of(2019, 11, 30));
        employees[8] = new Employee("Ivan", 37, 45000.00, "Sales", LocalDate.of(2017, 7, 4));
        employees[9] = new Employee("Judy", 22, 42000.00, "HR", LocalDate.of(2021, 3, 18));
        List<Employee> list = Arrays.asList(employees);

        //1.过滤特定部门的员工：给定一个员工列表，使用Stream API过滤出所有在"技术部"工作的员工。
        List<Employee> techEmployees = list.stream().filter(e -> "技术部".equals(e.getDepartment())).collect(Collectors.toList());
        //2.计算部门平均薪资：计算每个部门员工的平均薪资，并按平均薪资降序排列。
        Map<String, Double> collect = list.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.averagingDouble(Employee::getSalary)));
        //3.查找最年长员工：找出员工列表中最年长的员工。
        Optional<Employee> max = list.stream().max(Comparator.comparing(Employee::getAge));
        Employee employee = max.get();
        //4.员工分组：将员工按照部门进行分组，并计算每个部门的员工数量。
        Map<String, Long> collected = list.stream().collect(Collectors.groupingBy(Employee::getDepartment, Collectors.counting()));
        //5.过滤并映射：过滤出薪资高于平均值的员工，并将他们的名字转换为大写。
        List<Employee> employeeList = list.stream().filter(emp -> emp.getSalary() > list.stream().collect(Collectors.averagingDouble(Employee::getSalary))).collect(Collectors.toList());
        List<String> upCaseName = employeeList.stream().map(a -> {
            String name = a.getName().toUpperCase();
            return name;
        }).collect(Collectors.toList());

        List<String> collect1 = list.stream().filter(emp -> emp.getSalary() > list.stream().collect(Collectors.averagingDouble(Employee::getSalary))).collect(Collectors.toList()).stream().map(a -> {
            return a.getName().toUpperCase();
        }).collect(Collectors.toList());
        List<String> highEarnersNamesUpperCase = list.stream()
                .filter(e -> e.getSalary() > list.stream().collect(Collectors.averagingDouble(Employee::getSalary)))
                .map(e -> e.getName().toUpperCase())
                .collect(Collectors.toList());
        //6.收集统计信息：收集员工列表中所有员工的总薪资、平均年龄和入职日期的中位数。
        Map map = new HashMap();
        List<Double> list1 = list.stream().map(emp -> {
            double salaryTotal = 0;
            salaryTotal += emp.getSalary();
            return salaryTotal;
        }).collect(Collectors.toList());

        double totalSalary = list.stream()
                .mapToDouble(Employee::getSalary)
                .sum();
        double averageAge = list.stream()
                .mapToInt(Employee::getAge)
                .average()
                .orElse(0);
        LocalDate medianHireDate = list.stream()
                .sorted(Comparator.comparing(Employee::getHireDate))
                .map(Employee::getHireDate)
                .collect(Collectors.toList())
                .get(list.size() / 2);
        //7.扁平化列表：给定一个员工列表的列表，扁平化成一个单一的员工列表。
        /**
         * 扁平化处理通常指的是将一个嵌套结构（例如列表的列表）转换成一个单层结构（单一列表）的过程
         * Java Stream API中，flatMap操作是用来实现扁平化的一种方法。flatMap与map不同，map操作符会将一个流中的每个元素转换成另一个对象，
         * 但不会改变流中元素的数量——输入流中的每个元素映射成输出流中的一个元素。而flatMap则可以接收一个函数，该函数将流中的每个元素转换成一个流，然后将所有的流连接起来，形成一个统一的流
         */
        /**
         * 这里的employeesList假设是一个List<List<Employee>>，即员工列表的列表。flatMap(List::stream)调用的List::stream是一个方法引用，
         * 它对于每个List<Employee>获取其流，然后flatMap将这些流连接起来，形成一个新的流，其中包含所有嵌套列表中的员工。最后，通过collect(Collectors.toList())将流中的元素收集到一个新的列表中。
         */
        List<List<Employee>> employeesList = new ArrayList<>();
        employeesList.add(list);
        List<Employee> flattenedEmployeeList = employeesList.stream()
                .flatMap(List::stream)
                .collect(Collectors.toList());
        //8.查找入职时间最早的员工：找出所有员工中入职时间最早的员工。
        Employee employee1 = list.stream().min(Comparator.comparing(Employee::getHireDate)).get();
        //9.员工薪资排名：根据员工薪资进行排名，并返回排名前三的员工。
        List<Employee> employeeList1 = list.stream().sorted(Comparator.comparingDouble(Employee::getSalary).reversed()).limit(3).collect(Collectors.toList());
        //10.复杂条件过滤：过滤出年龄在30到40岁之间，并且薪资高于部门平均薪资的员工。
        List<Employee> collect2 = list.stream().filter(e -> e.getAge() >= 30 && e.getAge() <= 40).filter(a -> a.getSalary() > list.stream().collect(Collectors.averagingDouble(Employee::getSalary))).collect(Collectors.toList());

    }
}
